/**
 * Client-side application layer.
 *
 * @author Timothy Flynn (trflynn@wpi.edu)
 * @modified JTM 2012/04/11
 * @version April 11, 2012
 */
#include <queue>
#include <pthread.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
using std::queue;
using std::cout;
using std::cerr;
using std::endl;

#include "common.h"
#include "Packet.h"
#include "Frame.h"
#include "DataLinkLayer.h"
#include "PhysicalLayer.h"
#include "ApplicationLayer.h"

// Queues to store frames/packets for inter-level comm
queue<Packet *> sendPktQ, recvPktQ;
queue<Frame *> sendFrameQ, recvFrameQ;

// Semaphores to protect access to queues
pthread_mutex_t sendPktM, recvPktM;
pthread_mutex_t sendFrameM, recvFrameM;

int main(int argc, char **argv) {
	pthread_mutex_init(&sendPktM, NULL);
	pthread_mutex_init(&recvPktM, NULL);
	pthread_mutex_init(&sendFrameM, NULL);
	pthread_mutex_init(&recvFrameM, NULL);

	ApplicationLayer *app = new ApplicationLayer(false);
	PhysicalLayer *phys = new PhysicalLayer("localhost");
	DataLinkLayer *data = new DataLinkLayer();

//	Packet *p = new Packet();
//		p->type = DATA;
//		p->end = true;
//		p->seq = 0;
//		p->length = 14;
//		p->data = (char *)malloc((p->length+1) * sizeof(char));
//		memcpy(p->data, (char *)"WHADDUP SERVER", p->length);
//		p->data[p->length] = '\0';
//		sendPktQ.push(p);

	// Launch DL and PL threads
	pthread_t pt, dt;
	pthread_create(&dt, NULL, runDataLinkLayer, data);
	pthread_create(&pt, NULL, runPhysicalLayer, phys);

	// For now, send dummy packet
	app->run();
//	while(true){
//		pthread_mutex_lock(&recvPktM);
//		if(!recvPktQ.empty()) {
//			Packet *p2 = recvPktQ.front();
//			recvPktQ.pop();
//			cout << "Client: Got packet! " << p2->data << endl;
//			break; // just exit for now
//		}
//		pthread_mutex_unlock(&recvPktM);
//	}

	return 0;
}
